#ifndef __GRAPHIC_PARTICLE_SYSTEM__
    #define __GRAPHIC_PARTICLE_SYSTEM__

    // .. REFERENCES

    #include "object.h"
	#include "primitives.h"
    #include "graphic_particle_displayer.h"
    #include "graphic_particle_emitter.h"   
    class GRAPHIC_PARTICLE_MODIFIER;
    #include "graphic_particle_modifier.h"
    #include "graphic_particle_table.h"
	#include "defs.h"

    // .. TYPES

    class GRAPHIC_PARTICLE_SYSTEM :
        public OBJECT
    {
        // -- PUBLIC

    public :

        // .. TYPES

        DECLARE_REF( GRAPHIC_PARTICLE_SYSTEM );

        // ~~

        enum FLAG
        {
            FLAG_UsePosition =      0x00000001,
            FLAG_UseColor =         0x00000002,
            FLAG_UseOrientation =   0x00000004,
            FLAG_UseExtent =        0x00000008,
            FLAG_UseVelocity =      0x00000010,
            FLAG_UseLifeTime =      0x00000020
        };

        // .. CONSTRUCTORS

        GRAPHIC_PARTICLE_SYSTEM();

        // .. ACCESSORS

        VOID SetDisplayer(
            const GRAPHIC_PARTICLE_DISPLAYER::REF & displayer
            )
        {
            Displayer = displayer;
        }

        // ~~

        const GRAPHIC_PARTICLE_DISPLAYER::REF & GetDisplayer() const
        {
            return Displayer;
        }

        // ~~

        VOID SetEmitter(
            const GRAPHIC_PARTICLE_EMITTER::REF & emitter
            )
        {
            Emitter = emitter;
        }

        // ~~

        const GRAPHIC_PARTICLE_EMITTER::REF & GetEmitter() const
        {
            return Emitter;
        }

        // .. INQUIRIES

        BOOL IsSetFlag(
            const FLAG flag 
            )
        {
            return Flags == ( Flags & flag );
        }

        // .. OPERATIONS

        virtual VOID Initialize(
            const COUNT particle_count,
            const TEXT & particle_texture
            );

        // ~~

        VOID LoadFromFile(
            const TEXT & filename
            );

        // ~~

        virtual VOID Update(
            const TIMER & time_step
            );

        // ~~

        virtual VOID Reset();

        // ~~

        virtual VOID Render();

        // ~~

        VOID AddModifier(
            const REF_TO_< GRAPHIC_PARTICLE_MODIFIER > & modifier
            );

        // ~~ 

        VOID SetPosition(
            const MATH_VECTOR_3 & position
            );

        // ~~

        VOID SetFlag(
            const FLAG flag 
            )
        {
            Flags = Flags | flag;
        }

        // ~~

        VOID UnsetFlag(
            const FLAG flag 
            )
        {
            Flags = Flags & ~flag;
        }

        // ~~

        VOID Pause(
            const BOOL it_must_pause
            );

        // ~~

        VOID PauseEmitter(
            const BOOL emitter_must_be_paused
            );

        // ~~

        VOID SetParticleShader( const GRAPHIC_SHADER_PROGRAM::REF shader )
        {
        	Displayer->SetParticleShader( shader );
        }

        // -- PRIVATE

    private :

        // .. CONSTRUCTORS

        GRAPHIC_PARTICLE_SYSTEM(
            const GRAPHIC_PARTICLE_SYSTEM & other
            );

        // .. OPERATORS

        GRAPHIC_PARTICLE_SYSTEM & operator=(
            const GRAPHIC_PARTICLE_SYSTEM & other
            );

        // .. ATTRIBUTES

        GRAPHIC_PARTICLE_TABLE
            ParticleTable;
        GRAPHIC_PARTICLE_EMITTER::REF
            Emitter;
        ARRAY< REF_TO_< GRAPHIC_PARTICLE_MODIFIER > >
            ModifierTable;
        GRAPHIC_PARTICLE_DISPLAYER::REF
            Displayer;
        UINT32
            Flags;
        BOOL
            ItIsPaused,
            EmissionIsPaused;
    };
#endif
